package com.lengxf.minio.config;

import com.lengxf.minio.model.CredentialsDTO;
import io.minio.*;
import io.minio.credentials.AssumeRoleProvider;
import io.minio.http.Method;
import io.minio.messages.DeleteObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.Arrays;
import java.util.List;


@Slf4j
@Component
public class MinioService {

    private final MinioProperties configuration;
    private final MinioClient minioClient;
    private final String bucket;

    /**
     * minio 参考文档 @see <a href="https://min.io/docs/minio/linux/developers/java/API.html">https://min.io/docs/minio/linux/developers/java/API.html</a>
     *
     * @Author Lengxf
     */
    @SneakyThrows
    public MinioService(MinioProperties configuration) {
        this.configuration = configuration;
        this.minioClient = configuration.client();
        bucket = configuration.getBucket();
        if (!bucketExists()) {
            makeBucket();
        }
    }

    @SneakyThrows
    public CredentialsDTO getCredentials() {
        AssumeRoleProvider provider = new AssumeRoleProvider(configuration.getEndpoint(), configuration.getAccessKey(),
                configuration.getSecretKey(), configuration.getExpire(),
                null, null, null, null, null, null);
        return new CredentialsDTO(provider.fetch(), configuration.getExpire());
    }

    @SneakyThrows
    private Boolean bucketExists() {
        return minioClient.bucketExists(BucketExistsArgs.builder()
                .bucket(bucket)
                .build());
    }

    @SneakyThrows
    private void makeBucket() {
        minioClient.makeBucket(MakeBucketArgs.builder()
                .bucket(bucket)
                .build());
    }

    @SneakyThrows
    public InputStream getObject(String objectKey) {
        return minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucket).object(objectKey)
                .build());
    }


    /**
     * @param fileName 路径+文件名字+后缀 如果不加则会下载至当前目录
     * @Author Lengxf
     */
    @SneakyThrows
    public void downloadObject(String objectKey, String fileName) {
        minioClient.downloadObject(DownloadObjectArgs.builder()
                .bucket(bucket).object(objectKey).filename(fileName)
                .overwrite(true)
                .build());
    }

    @SneakyThrows
    public String getObjectUrl(String objectKey) {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .method(Method.GET).bucket(bucket).object(objectKey).expiry(configuration.getExpire())
                .build());
    }

    @SneakyThrows
    public void upload(String objectKey, MultipartFile file) {
        InputStream inputStream = file.getInputStream();
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucket).object(objectKey).stream(inputStream, inputStream.available(), -1)
                .contentType(file.getContentType())
                .build());
    }

    public String uploadAndGetUrl(String objectKey, MultipartFile file) {
        upload(objectKey, file);
        return getObjectUrl(objectKey);
    }


    /**
     * 官方提供了此API 实际并未生效 服务端镜像为最新版镜像
     *
     * @Date 2022年11月23日17:28:56
     * @Author Lengxf
     */
    public void remove(String... objectKey) {
        List<DeleteObject> deleteObjectList = Arrays.stream(objectKey).map(DeleteObject::new).toList();
        minioClient.removeObjects(RemoveObjectsArgs.builder()
                .bucket(bucket).objects(deleteObjectList)
                .build());
    }

    @SneakyThrows
    public void remove(String objectKey) {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket)
                .object(objectKey)
                .build());
    }

}
